<script setup lang="ts">
import { useTimeoutFn } from '@vueuse/core';
import { getLastOffset, getOffsetOrSpace } from './message';
import {
    InfoFilled,
    CircleCheckFilled,
    WarningFilled,
    CircleCloseFilled
} from '@element-plus/icons-vue';
import { ElIcon } from 'element-plus';
import type { MessageType } from './type';

const props = withDefaults(defineProps<MessageType>(), {
    type: 'pending',
    unAutoClose: false,
    top: 20,
    closeTime: 3,
    close
});

const emit = defineEmits(['close', 'destroy']);
const visible = ref(false); //控制弹框

let stopTimer: (() => void) | undefined = undefined; // 控制定时器

onMounted(() => {
    visible.value = true;
    if (!props.unAutoClose && props.type !== 'pending') {
        startTimer();
    }
});

// 鼠标移入关闭定时器
function startTimer() {
    ({ stop: stopTimer } = useTimeoutFn(() => {
        visible.value = false;
    }, +props.closeTime * 1000));
}

// 鼠标移出重置并开启定时器
function clearTimer() {
    stopTimer?.();
}

const bottom = computed((): number => 44 + offset.value);
const lastOffset = computed(() => getLastOffset(props.id));
const offset = computed(() => getOffsetOrSpace(props.id, props.top) + lastOffset.value);

// message类型映射
const typeMap = {
    info: {
        icon: InfoFilled,
        bg: '#cce0ff',
        nbg: '#06F'
    },
    pending: {
        icon: InfoFilled,
        bg: '#cce0ff',
        nbg: '#06F'
    },
    success: {
        icon: CircleCheckFilled,
        bg: '#ccf1d5',
        nbg: '#00BB2C'
    },
    warning: {
        icon: WarningFilled,
        bg: '#ffe7d0',
        nbg: '#FF8713'
    },
    error: {
        icon: CircleCloseFilled,
        bg: '#fedada',
        nbg: '#FC4848'
    }
};
defineExpose({
    bottom,
    visible
});
</script>
<template>
    <div :id="id" class="message-box" :style="{ marginLeft: left }">
        <q-mask v-if="type === 'pending' || unAutoClose" v-model="visible" />
        <transition
            name="fade-message"
            @before-leave="emit('close')"
            @after-leave="emit('destroy')"
        >
            <div
                v-show="visible"
                class="message f14"
                :style="{ marginTop: offset + 'px', background: typeMap[type].bg }"
                @mouseenter="clearTimer"
                @mouseleave="startTimer"
            >
                <div id="message_component" class="message__content">
                    <el-icon
                        size="16"
                        style="margin-right: 8px; margin-bottom: 1px"
                        :color="typeMap[type].nbg"
                    >
                        <div v-if="type === 'pending'" class="message__content--loading"></div>
                        <template v-else>
                            <component :is="typeMap[type].icon"></component>
                        </template>
                    </el-icon>
                    <div class="message__content--text" :style="{ color: typeMap[type].nbg }">
                        {{ text }}
                    </div>
                </div>

                <div v-if="type !== 'pending'" class="message__close" @click="visible = false">
                    <svg
                        xmlns="http://www.w3.org/2000/svg"
                        width="16"
                        height="16"
                        viewBox="0 0 16 16"
                        fill="none"
                    >
                        <path
                            d="M11.9375 3.35951L7.99996 7.29701L4.06246 3.35951C3.95812 3.26584 3.84096 3.21901 3.71096 3.21901C3.58096 3.21901 3.46629 3.26851 3.36696 3.36751C3.26762 3.46651 3.21812 3.58117 3.21846 3.71151C3.21879 3.84184 3.26562 3.95901 3.35896 4.06301L7.29646 8.00051L3.35896 11.938C3.22362 12.0733 3.17929 12.2348 3.22596 12.4225C3.27262 12.6102 3.38729 12.7273 3.56996 12.774C3.75262 12.8207 3.91662 12.7763 4.06196 12.641L7.99946 8.70351L11.937 12.641C12.0413 12.7347 12.1585 12.7815 12.2885 12.7815C12.4185 12.7815 12.5331 12.732 12.6325 12.633C12.7318 12.534 12.7813 12.4193 12.781 12.289C12.7806 12.1587 12.7338 12.0415 12.6405 11.9375L8.70296 8.00001L12.6405 4.06251C12.7758 3.92717 12.8201 3.76567 12.7735 3.57801C12.7268 3.39034 12.6096 3.27317 12.422 3.22651C12.2343 3.17984 12.0728 3.22417 11.9375 3.35951Z"
                            fill="#595959"
                        />
                    </svg>
                </div>
            </div>
        </transition>
    </div>
</template>

<style scoped lang="scss">
.message-box {
    position: fixed;
    top: 20px;
    left: 50%;
    z-index: 999999;
    transform: translateX(-50%);
}

@include b(message) {
    display: flex;
    align-items: center;
    overflow: hidden;
    backdrop-filter: blur(10px);
    border-radius: 4px;
    transition: all 0.3s;

    @include e(content) {
        display: flex;
        align-items: center;
        padding: 16px 8px 14px 16px;
        color: #fff;

        @include m(text) {
            max-width: 600px;
            line-height: 15px;
        }

        // loading
        @include m(loading) {
            width: 14px;
            height: 14px;
            border: 2px solid transparent;
            border-top-color: #06f;
            border-radius: 14px;
            animation-name: loading-animation;
            animation-duration: 2s;
            animation-timing-function: linear;
            animation-iteration-count: infinite;
        }
    }

    @include e(close) {
        display: flex;
        align-items: center;
        padding: 16px 16px 16px 8px;
        cursor: pointer;
    }
}

// loading动画
@keyframes loading-animation {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

.fade-message-enter-from {
    opacity: 0;
    transform: translateY(0);
}

.fade-message-enter-to {
    transform: translateY(30px);
}

.fade-message-enter-active {
    transition: all 0.2s var(--q-bounce-function);
}

.fade-message-leave-to {
    opacity: 0;
    transform: translateY(-50px);
}
</style>
